//---------------------------------------------------------------------------
// CSignal Class
// Author : Woo-Hyun Kim
// Email : woorung@nhncorp.com
// Date : Apr. 7, 2008
//---------------------------------------------------------------------------
#include "CSignal.h"
//---------------------------------------------------------------------------
// static global parameters
CSignal *CSignal::_instance = NULL;
CSignalHandler *CSignal::_signal_handlers[NSIG];
//---------------------------------------------------------------------------
CSignal::CSignal() 
{
	_instance = this;

	for(int i=0;i<NSIG;i++) _signal_handlers[i] = 0;
}
//---------------------------------------------------------------------------
void CSignal::dispatcher(int signum, siginfo_t *si, void *sv)
{
	// after catching all the signals, dispatch them to the assigned handlers
	if(CSignal::_signal_handlers[signum]!=0) {
		CSignal::_signal_handlers[signum]->handle(signum, si, sv);
	}
}
//---------------------------------------------------------------------------
CSignal *CSignal::instance(void)
{
	return _instance;
}
//---------------------------------------------------------------------------
// signal mask-related functions
//---------------------------------------------------------------------------
void CSignal::block(CSignalMask *sigmask)
{
	sigmask->block();
}
//---------------------------------------------------------------------------
void CSignal::unblock(CSignalMask *sigmask)
{
	sigmask->unblock();
}
//---------------------------------------------------------------------------
void CSignal::setmask(CSignalMask *sigmask)
{
	sigmask->setmask();
}
//---------------------------------------------------------------------------
void CSignal::setinit(CSignalMask *sigmask)
{
	sigmask->setinit();
}
//---------------------------------------------------------------------------
int CSignal::trigger(pid_t pid, int signum, const union sigval sv)
{
	return sigqueue(pid, signum, sv);
}
//---------------------------------------------------------------------------
int CSignal::waitinfo(CSignalMask *&sigmask)
{
	return sigmask->waitinfo();
}
//---------------------------------------------------------------------------
int CSignal::timedwaitinfo(CSignalMask *&sigmask, const struct timespec *timeout)
{
	return sigmask->timedwaitinfo(timeout);
}
//---------------------------------------------------------------------------
// signal handler-related functions
//---------------------------------------------------------------------------
CSignalHandler *CSignal::register_handler(int signum, CSignalHandler *sig_handler)
{
	CSignalHandler *old_sig_handler = CSignal::_signal_handlers[signum];
	CSignal::_signal_handlers[signum] = sig_handler;

	// always set a static signal handler for all the signals
	struct sigaction act;
	sigemptyset(&act.sa_mask);
	act.sa_restorer = NULL;
	act.sa_sigaction = CSignal::dispatcher;
	act.sa_flags = SA_SIGINFO | SA_RESTART;

	if(sigaction(signum,&act,0)==1) {
		cerr << "### signal error" << endl;
		exit(-1);
	}

	return old_sig_handler;
}
//---------------------------------------------------------------------------
CSignalHandler *CSignal::get_handler(int signum)
{
	return CSignal::_signal_handlers[signum];
}
//---------------------------------------------------------------------------
int CSignal::remove_handler(int signum)
{
	CSignal::_signal_handlers[signum] = 0;
}
//---------------------------------------------------------------------------
